package com.xgp.weixinxgp.tool;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.thoughtworks.xstream.XStream;
import com.xgp.weixinxgp.model.*;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.net.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class WxTool {

    private static final String TOKEN = "xgp";
    private static final String methodUrl = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=";

    private static final String APPID = "wx6d1c6dd47da7e7d1";
    private static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    private static final String APPSECRET = "7dd676d27f8eabe1a8294b4f6983b1fa";

    //用于存储token
    public static AccessToken at = null;

    /**
     * 发送post请求
     * @return
     */
    public static String post(String url,String data) {
        URL urlObj = null;
        try {
            urlObj = new URL(url);
            URLConnection con = urlObj.openConnection();
            //要发送数据出去，必须设置为可发送的数据状态
            con.setDoOutput(true);
            //获取输出流
            OutputStream os = con.getOutputStream();
            //写出数据
            os.write(data.getBytes());
            os.close();
            //获取输入流，读取数据
            InputStream is = con.getInputStream();
            byte[] b = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            while((len = is.read(b)) != -1) {
                sb.append(new String(b,0,len));
            }
            return sb.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取token
     */
    private static void getToken() {
        String url = GET_TOKEN_URL.replace("APPID",APPID).replace("APPSECRET",APPSECRET);
//        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx6d1c6dd47da7e7d1&secret=7dd676d27f8eabe1a8294b4f6983b1fa";
        //忽略https证书
        HttpsUrlValidator.retrieveResponseFromServer(url);
        String tokenStr = get(url);
        System.out.println(tokenStr);
        JSONObject jsonobj = JSONObject.fromObject(tokenStr);
        String token = jsonobj.getString("access_token");
        String expireIn = jsonobj.getString("expires_in");
        //创建token对象
        at = new AccessToken(token,expireIn);

    }

    /**
     * 向外暴露获取token的方法
     * @return
     */
    public static String getAccessToken() {
        if(at == null || at.isExpired()){
            getToken();
        }
        return at.getAccessToken();
    }

    /**
     * java发送http请求
     */
    public static String get(String url) {
        try {
            URL urlObj = new URL(url);
            //开连接
            URLConnection con = urlObj.openConnection();
            InputStream is = con.getInputStream();
            byte[] b = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            while((len = is.read(b)) != -1) {
                sb.append(new String(b,0,len));
            }
            return sb.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static boolean check(String timestamp,String nonce, String signature) {
        /**
         开发者通过检验signature对请求进行校验（下面有校验方式）。
         若确认此次GET请求来自微信服务器，请原样返回echostr参数内容，
         则接入生效，成为开发者成功，否则接入失败。加密/校验流程如下：
            1）将token、timestamp、nonce三个参数进行字典序排序
            2）将三个参数字符串拼接成一个字符串进行sha1加密
            3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
         */

        String[] strs = new String[] {TOKEN,timestamp,nonce};
        Arrays.sort(strs);

        String str = strs[0] + strs[1] + strs[2];
        String mysig = shal(str);

        return mysig.equalsIgnoreCase(signature);
    }

    /**
     *  进行shal加密
     * @param src
     * @return
     */
    private static String shal(String src) {
        //获取一个加密的对象
        try {
            MessageDigest md = MessageDigest.getInstance("sha1");
            //加密
            byte[] digest = md.digest(src.getBytes());
            //处理加密结果
            char[] chars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
            StringBuffer sb = new StringBuffer();
            for (byte b : digest) {
                sb.append(chars[(b >> 4) & 15]);
                sb.append(chars[b & 15]);
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return null;
    }


    public static Map<String, String> parseRequest(InputStream is) {
        Map<String,String> map = new HashMap<>();
        SAXReader reader = new SAXReader();
        try {
            //读取输入流获取文档对象
            Document dom = reader.read(is);
            //根据文档对象，获取根节点
            Element root = dom.getRootElement();
            //获取根节点的所有的子节点
            List<Element> elements = root.elements();
            for (Element element : elements) {
                map.put(element.getName(),element.getStringValue());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    public static String getResponse(Map<String, String> requestMap) {
        BaseMessage msg = null;
        String msgType = requestMap.get("MsgType");
        switch (msgType) {
            case "text":
                msg = dealTextMessage(requestMap);
                break;
            case "image":break;
            case "voice":break;
            case "video":break;
            case "news":break;
            case "shortvideo":break;
            case  "location":break;
            case  "link":break;
        }
        //把消息对象处理为Xml数据包
        if(msg != null) {
            return beanToXml(msg);
        }
        return null;
    }

    private static String beanToXml(BaseMessage msg) {
        XStream stream = new XStream();
        //需要处理注解的类
        stream.processAnnotations(TextMessage.class);
        stream.processAnnotations(ImageMessage.class);
        stream.processAnnotations(MusicMessage.class);
        stream.processAnnotations(NewsMessage.class);
        stream.processAnnotations(VideoMessage.class);
        stream.processAnnotations(VoiceMessage.class);
        String xml = stream.toXML(msg);
        return xml;
    }

    /**
     * 处理文本消息
     * @param requestMap
     * @return
     */
    private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
        //用户发来的内容
        String msg = requestMap.get("Content");
        if("图文".equals(msg)) {
/**            {MediaId=Q69OOFY4aAFejM3zuYdGG_y-s1pnxwS3h9WYeLfPJpqL6MHY47q6UAw4kaeaSH2S,
 * CreateTime=1581339675,
 * ToUserName=gh_8b8c82de0c23,
 * FromUserName=ooxPDs4H6AhlKgMsX9nuiCZWfH5o,
 * MsgType=image,
 * PicUrl=http://mmbiz.qpic.cn/mmbiz_jpg/5DrJVKaKkK5Sr46aHkmxIs20eIib57wapjvKeIsjZzpkOF55R1ZECVZK1qfbv06Hx4s0DfcqcpMqbhDjicnVFkJw/0,
 * MsgId=22639341123370541}
**/
            List<Article> articles = new ArrayList<>();
            articles.add(new Article("这是图文消息","这是图文的详细信息","http://mmbiz.qpic.cn/mmbiz_jpg/5DrJVKaKkK5Sr46aHkmxIs20eIib57wapjvKeIsjZzpkOF55R1ZECVZK1qfbv06Hx4s0DfcqcpMqbhDjicnVFkJw/0","http://www.baidu.com"));
            NewsMessage nm = new NewsMessage(requestMap,articles);
            return nm;
        }
        //调用接口
        //1，青峰云的接口
        String resp = chat(msg);
        TextMessage tm = new TextMessage(requestMap,resp);
        return tm;
    }

    /**
     * 聊天的接口
     * @param msg
     * @return
     */
    private static String chat(String msg) {
        URL url = null;
        try {
            url = new URL(methodUrl + msg);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        HttpURLConnection connection = null;// 根据URL生成HttpURLConnection
        try {
            connection = (HttpURLConnection) url.openConnection();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            connection.setRequestMethod("GET");// 默认GET请求
        } catch (ProtocolException e) {
            e.printStackTrace();
        }
        try {
            connection.connect();// 建立TCP连接
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));// 发送http请求
                StringBuilder result = new StringBuilder();
                // 循环读取流
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line).append(System.getProperty("line.separator"));// "\n"
                }
                return getMsg(result.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * j解析json数据
     * @param toString
     * @return
     */
    private static String getMsg(String toString) {
        String[] str = toString.split(":");
        return str[str.length -1].substring(1,str[str.length -1].length() - 4);
    }
}
